{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Part 1, Topic 1, Lab A: Fault Attacks and Cryptography"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "NOTE: This lab references some (commercial) training material on [ChipWhisperer.io](https://www.ChipWhisperer.io). You can freely execute and use the lab per the open-source license (including using it in your own courses if you distribute similarly), but you must maintain notice about this source location. Consider joining our training course to enjoy the full experience.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**SUMMARY:** *In SCA101, we explored how cryptographic systems are vulnerable to power analysis and recovered an AES key . In Fault101, you saw how by inserting glitches into a device's power supply or clock we can disrupt its operation, skipping instructions and corrupting variables. In Fault202, we'll applying the glitching we learned in Fault101 to break the cryptographic systems we learned about in SCA101.*\n",
    "\n",
    "*In this lab, we'll explore how a theoretical fault can let us break AES in just 3 plaintext and ciphertext pairs.*\n",
    "\n",
    "**LEARNING OUTCOMES:**\n",
    "* Identifying potential fault locations in AES\n",
    "* Simulating Faults\n",
    "* Using faults to break AES\n",
    "\n",
    "## The Fault Model\n",
    "\n",
    "As you might expect, there are many, many different fault attacks against cryptography. Some have requirements that are pretty easy to achieve via fault injection. For example, an attack that we'll look at in a later lab only requires that you fault a single byte just before the last/second last MixColumns operation in AES. Others have more precise requirements that can be difficult to realize in practice, such as only flipping specific bits in the AES state. To give you an easy introduction to fault attacks on AES in particular, we'll be simulating a pretty simple attack that can remove all of the security of AES. To start, recall the structure of AES:\n",
    "\n",
    "![](img/aes_operations.png)\n",
    "(source: http://www.iis.ee.ethz.ch/~kgf/acacia/fig/aes.png)\n",
    "\n",
    "The basis of AES's cryptographic security is in those repeated round operations. There, the different bytes of the state are combined, shifted around, and obfuscated such that even the best attacks are only marginally faster than just guessing all the possible keys. What if, however, we simply skipped all of that and moved directly from the first AddRoundKey to the start of the last round? Suddenly, we're withing striking distance of a single byte search space, meaning we take our search space from $2^{128}$ to $16*2^8$ like we had with power analysis! If we go through the operations of AES:\n",
    "\n",
    "```python\n",
    "pt = [...]                \n",
    "state = AddRoundKey(pt, 0)   # pt ^ K0\n",
    "state = SBox(state)          # SBox(pt ^ K0)\n",
    "state = ShiftRows(state)     # Changes which pt goes with which output\n",
    "output = AddRoundKey(pt, 10) # SBox(pt ^ K0) ^ K10\n",
    "```\n",
    "\n",
    "We can see that the bytes of state are never mixed together. If we could get rid of that final `AddRoundKey` command, we'd have reached our goal of a $16*2^8$ search space, which is actualy quite easy to do! Remembering that XOR is the inverse of itself, all we have to do to get rid of K10 is collect another of these faults with a different plaintext, and XOR them together:\n",
    "\n",
    "```\n",
    "output0 = SBox(pt0 ^ K0) ^ K10\n",
    "output1 = SBox(pt1 ^ K0) ^ K10\n",
    "output0 ^ output1 = SBox(pt0 ^ K0) ^ SBox(pt1 ^ K0) ^ K10 ^ K10\n",
    "output0 ^ output1 = SBox(pt0 ^ K0) ^ SBox(pt1 ^ K0)\n",
    "```\n",
    "\n",
    "From there, we can test different K0s in that final equation until we've found our key!.\n",
    "\n",
    "Let's test our theory with a single byte fault:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "key = 0x2b #unknown\n",
    "key1 = 0xad #unknown\n",
    "\n",
    "sbox = [\n",
    "    # 0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f \n",
    "    0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, # 0\n",
    "    0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, # 1\n",
    "    0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, # 2\n",
    "    0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, # 3\n",
    "    0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, # 4\n",
    "    0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, # 5\n",
    "    0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, # 6\n",
    "    0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, # 7\n",
    "    0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, # 8\n",
    "    0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, # 9\n",
    "    0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, # a\n",
    "    0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, # b\n",
    "    0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, # c\n",
    "    0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, # d\n",
    "    0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, # e\n",
    "    0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16  # f\n",
    "]\n",
    "\n",
    "def generate_glitch(pt):\n",
    "    state = pt ^ key\n",
    "    state = sbox[state]\n",
    "    return state ^ key1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now generate faulty outputs by calling this function with a plaintext:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "P0 = 0\n",
    "P1 = 0x10\n",
    "\n",
    "O0 = generate_glitch(P0)\n",
    "O1 = generate_glitch(P1)\n",
    "print(O0, O1, O0 ^ O1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now write some code to test different keys and print out successful guesses for the key:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(255):\n",
    "    if (sbox[i ^ P0] ^ sbox[i ^ P1]) == (O0 ^ O1):\n",
    "        print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should see two candidates for the key. This can be narrowed down to one by adding another faulty plaintext."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "P2 = 3\n",
    "O2 = generate_glitch(P2)\n",
    "for i in range(255):\n",
    "    if (sbox[i ^ P0] ^ sbox[i ^ P1]) == (O0 ^ O1):\n",
    "        if (sbox[i ^ P0] ^ sbox[i ^ P2] == (O2 ^ O0)):\n",
    "            print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusions & Next Steps\n",
    "\n",
    "As you've seen in this lab, if we can use fault injection to skip important bits of AES, it becomes trivial to break. You might be wondering about the practicality of such an attack. In the next lab, we'll be taking a look at this attack on hardware, specifically targetting TINYAES128C."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "<small>NO-FUN DISCLAIMER: This material is Copyright (C) NewAE Technology Inc., 2015-2020. ChipWhisperer is a trademark of NewAE Technology Inc., claimed in all jurisdictions, and registered in at least the United States of America, European Union, and Peoples Republic of China.\n",
    "\n",
    "Tutorials derived from our open-source work must be released under the associated open-source license, and notice of the source must be *clearly displayed*. Only original copyright holders may license or authorize other distribution - while NewAE Technology Inc. holds the copyright for many tutorials, the github repository includes community contributions which we cannot license under special terms and **must** be maintained as an open-source release. Please contact us for special permissions (where possible).\n",
    "\n",
    "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</small>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
